home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / TCPIN.C < prev    next >
C/C++ Source or Header  |  1989-06-18  |  23KB  |  856 lines

  1. /* Process incoming TCP segments. Page number references are to ARPA RFC-793,
  2.  * the TCP specification.
  3.  */
  4.  
  5. #include "global.h"
  6. #include "timer.h"
  7. #include "mbuf.h"
  8. #include "netuser.h"
  9. #include "internet.h"
  10. #include "tcp.h"
  11. #include "icmp.h"
  12. #include "iface.h"
  13. #include "ip.h"
  14.  
  15. struct tcp_stat tcp_stat;
  16.  
  17. /* This function is called from IP with the IP header in machine byte order,
  18.  * along with a mbuf chain pointing to the TCP header.
  19.  */
  20. void
  21. tcp_input(bp,protocol,source,dest,tos,length,rxbroadcast)
  22. struct mbuf *bp;    /* Data field, if any */
  23. char protocol;        /* Should always be TCP_PTCL */
  24. int32 source;        /* Remote IP address */
  25. int32 dest;        /* Our IP address */
  26. char tos;        /* Type of Service */
  27. int16 length;        /* Length of data field */
  28. char rxbroadcast;    /* Incoming broadcast - discard if true */
  29. {
  30.     void reset(),update();
  31.     void proc_syn(),send_syn(),add_reseq(),get_reseq(),unlink_tcb();
  32.  
  33.     register struct tcb *tcb;    /* TCP Protocol control block */
  34.     struct tcp seg;            /* Local copy of segment header */
  35.     struct connection conn;        /* Local copy of addresses */
  36.     struct pseudo_header ph;    /* Pseudo-header for checksumming */
  37.     int hdrlen;            /* Length of TCP header */
  38.  
  39.     if(bp == NULLBUF)
  40.         return;
  41.  
  42.     if(rxbroadcast){
  43.         /* Any TCP packet arriving as a broadcast is
  44.          * to be completely IGNORED!!
  45.          */
  46.         tcp_stat.bdcsts++;
  47.         free_p(bp);
  48.         return;
  49.     }
  50.     ph.source = source;
  51.     ph.dest = dest;
  52.     ph.protocol = protocol;
  53.     ph.length = length;
  54.     if(cksum(&ph,bp,length) != 0){
  55.         /* Checksum failed, ignore segment completely */
  56.         tcp_stat.checksum++;
  57.         free_p(bp);
  58.         return;
  59.     }
  60.     /* Form local copy of TCP header in host byte order */
  61.     if((hdrlen = ntohtcp(&seg,&bp)) < 0){
  62.         /* TCP header is too small */
  63.         tcp_stat.runt++;
  64.         free_p(bp);
  65.         return;
  66.     }
  67.     length -= hdrlen;
  68.  
  69.     /* Fill in connection structure and find TCB */
  70.     conn.local.address = dest;
  71.     conn.local.port = seg.dest;
  72.     conn.remote.address = source;
  73.     conn.remote.port = seg.source;
  74.  
  75.     if((tcb = lookup_tcb(&conn)) == NULLTCB){
  76.         struct tcb *ntcb;
  77.         void link_tcb();
  78.  
  79.         /* Check that this segment carries a SYN, and that
  80.          * there's a LISTEN on this socket with
  81.          * unspecified source address and port
  82.          */
  83.         conn.remote.address = 0;
  84.         conn.remote.port = 0;
  85.         if(!(seg.flags & SYN) || (tcb = lookup_tcb(&conn)) == NULLTCB){
  86.             /* No unspecified LISTEN either, so reject */
  87.             free_p(bp);
  88.             reset(source,dest,tos,length,&seg);
  89.             return;
  90.         }
  91.         /* We've found an server listen socket, so clone the TCB */
  92.         if(tcb->flags & CLONE){
  93.             if((ntcb = (struct tcb *)malloc(sizeof (struct tcb))) == NULLTCB){
  94.                 free_p(bp);
  95.                 /* This may fail, but we should at least try */
  96.                 reset(source,dest,tos,length,&seg);
  97.                 return;
  98.             }
  99.             ASSIGN(*ntcb,*tcb);
  100.             tcb = ntcb;
  101.             tcb->timer.arg = (char *)tcb;
  102.             tcb->timeout.arg = (char *)tcb;
  103.         } else
  104.             unlink_tcb(tcb);    /* It'll be put back on later */
  105.  
  106.         /* Stuff the foreign socket into the TCB */
  107.         tcb->conn.remote.address = source;
  108.         tcb->conn.remote.port = seg.source;
  109.  
  110.         /* NOW put on right hash chain */
  111.         link_tcb(tcb);
  112.  
  113.         /* Start the timeout on transient state */
  114.         /* This is to prevent TCB's hanging in "SYN Rcvd" state */
  115.         /* when no retour route exists to a calling host */
  116.         start_timer(&tcb->timeout);
  117.     }
  118.     /* Do unsynchronized-state processing (p. 65-68) */
  119.     switch(tcb->state){
  120.     case CLOSED:
  121.         free_p(bp);
  122.         reset(source,dest,tos,length,&seg);
  123.         return;
  124.     case LISTEN:
  125.         if(seg.flags & RST){
  126.             free_p(bp);
  127.             return;
  128.         }
  129.         if(seg.flags & ACK){
  130.             free_p(bp);
  131.             reset(source,dest,tos,length,&seg);
  132.             return;
  133.         }
  134.         if(seg.flags & SYN){
  135.             /* (Security check is bypassed) */
  136.             /* page 66 */
  137.             tcp_stat.conin++;
  138.             proc_syn(tcb,tos,&seg);
  139.             send_syn(tcb);
  140.             setstate(tcb,SYN_RECEIVED);
  141.             if(length != 0 || (seg.flags & FIN)) {
  142.                 break;        /* Continue processing if there's more */
  143.             }
  144.             tcp_output(tcb);
  145.         }
  146.         free_p(bp);    /* Unlikely to get here directly */
  147.         return;
  148.     case SYN_SENT:
  149.         if(seg.flags & ACK){
  150.             if(!seq_within(seg.ack,tcb->iss+1,tcb->snd.nxt)){
  151.                 free_p(bp);
  152.                 reset(source,dest,tos,length,&seg);
  153.                 return;
  154.             }
  155.         }
  156.         if(seg.flags & RST){    /* p 67 */
  157.             if(seg.flags & ACK){
  158.                 /* The ack must be acceptable since we just checked it.
  159.                  * This is how the remote side refuses connect requests.
  160.                  */
  161.                 close_self(tcb,RESET);
  162.             }
  163.             free_p(bp);
  164.             return;
  165.         }
  166.         /* (Security check skipped here) */
  167.         /* Check incoming precedence; it must match if there's an ACK */
  168.         if((seg.flags & ACK) && PREC(tos) != PREC(tcb->tos)){
  169.             free_p(bp);
  170.             reset(source,dest,tos,length,&seg);
  171.             return;
  172.         }
  173.         if(seg.flags & SYN){
  174.             proc_syn(tcb,tos,&seg);
  175.             if(seg.flags & ACK){
  176.                 /* Our SYN has been acked, otherwise the ACK
  177.                  * wouldn't have been valid.
  178.                  */
  179.                 update(tcb,&seg);
  180.                 setstate(tcb,ESTABLISHED);
  181.             } else {
  182.                 setstate(tcb,SYN_RECEIVED);
  183.             }
  184.             if(length != 0 || (seg.flags & FIN)) {
  185.                 break;        /* Continue processing if there's more */
  186.             }
  187.             tcp_output(tcb);
  188.         } else {
  189.             free_p(bp);    /* Ignore if neither SYN or RST is set */
  190.         }
  191.         return;
  192.     }
  193.     /* We reach this point directly in any synchronized state. Note that
  194.      * if we fell through from LISTEN or SYN_SENT processing because of a
  195.      * data-bearing SYN, window trimming and sequence testing "cannot fail".
  196.      */
  197.  
  198.     /* Trim segment to fit receive window. */
  199.     if(trim(tcb,&seg,&bp,&length) == -1){
  200.         /* Segment is unacceptable */
  201.         if(!(seg.flags & RST)){
  202.             tcb->flags |= FORCE;
  203.             tcp_output(tcb);
  204.         }
  205.         return;
  206.     }
  207.     /* If segment isn't the next one expected, and there's data
  208.      * or flags associated with it, put it on the resequencing
  209.      * queue, ACK it and return.
  210.      *
  211.      * Processing the ACK in an out-of-sequence segment without
  212.      * flags or data should be safe, however.
  213.      */
  214.     if(seg.seq != tcb->rcv.nxt
  215.      && (length != 0 || (seg.flags & (SYN|FIN)) )){
  216.         add_reseq(tcb,tos,&seg,bp,length);
  217.         tcb->flags |= FORCE;
  218.         tcp_output(tcb);
  219.         return;
  220.     }
  221.     /* This loop first processes the current segment, and then
  222.      * repeats if it can process the resequencing queue.
  223.      */
  224.     for(;;){
  225.         /* We reach this point with an acceptable segment; all data and flags
  226.          * are in the window, and the starting sequence number equals rcv.nxt
  227.          * (p. 70)
  228.          */
  229.         if(seg.flags & RST){
  230.             if(tcb->state == SYN_RECEIVED
  231.              && !(tcb->flags & (CLONE|ACTIVE))){
  232.                 /* Go back to listen state only if this was
  233.                  * not a cloned or active server TCB
  234.                  */
  235.                 setstate(tcb,LISTEN);
  236.             } else {
  237.                 close_self(tcb,RESET);
  238.             }
  239.             free_p(bp);
  240.             return;
  241.         }
  242.         /* (Security check skipped here) p. 71 */
  243.         /* Check for precedence mismatch or erroneous extra SYN */
  244.         if(PREC(tos) != PREC(tcb->tos) || (seg.flags & SYN)){
  245.             free_p(bp);
  246.             reset(source,dest,tos,length,&seg);
  247.             return;
  248.         }
  249.         /* Check ack field p. 72 */
  250.         if(!(seg.flags & ACK)){
  251.             free_p(bp);    /* All segments after synchronization must have ACK */
  252.             return;
  253.         }
  254.         /* Process ACK */
  255.         switch(tcb->state){
  256.         case SYN_RECEIVED:
  257.             if(seq_within(seg.ack,tcb->snd.una+1,tcb->snd.nxt)){
  258.                 update(tcb,&seg);
  259.                 setstate(tcb,ESTABLISHED);
  260.             } else {
  261.                 free_p(bp);
  262.                 reset(source,dest,tos,length,&seg);
  263.                 return;
  264.             }
  265.             break;
  266.         case ESTABLISHED:
  267.         case CLOSE_WAIT:
  268.             update(tcb,&seg);
  269.             break;
  270.         case FINWAIT1:    /* p. 73 */
  271.             update(tcb,&seg);
  272.             if(tcb->sndcnt == 0){
  273.                 /* Our FIN is acknowledged */
  274.                 setstate(tcb,FINWAIT2);
  275.             }
  276.             break;
  277.         case FINWAIT2:
  278.             update(tcb,&seg);
  279.             break;
  280.         case CLOSING:
  281.             update(tcb,&seg);
  282.             if(tcb->sndcnt == 0){
  283.                 /* Our FIN is acknowledged */
  284.                 setstate(tcb,TIME_WAIT);
  285.                 tcb->timer.start = SEC2TICK(MSL2);
  286.                 start_timer(&tcb->timer);
  287.             }
  288.             break;
  289.         case LAST_ACK:
  290.             update(tcb,&seg);
  291.             if(tcb->sndcnt == 0){
  292.                 /* Our FIN is acknowledged, close connection */
  293.                 close_self(tcb,NORMAL);
  294.                 return;
  295.             }
  296. /* I think this is wrong, and can cause permanent ACK-ACK loops.  dmf.
  297.         case TIME_WAIT:
  298.             tcb->flags |= FORCE;
  299.             start_timer(&tcb->timer);
  300. */
  301.         }
  302.  
  303.         /* (URGent bit p